package cn.dlc.com.account.service.impl;

import cn.dlc.com.account.dao.AccountDao;
import cn.dlc.com.account.entity.Account;
import cn.dlc.com.account.service.AccountService;
import cn.dlc.com.log.dao.DuplicationDao;
import cn.dlc.com.log.entity.AccountChangeEvent;
import cn.dlc.com.log.entity.Duplication;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.UUID;

/**
 * @author 邓立川
 * @date 2021/1/12 16:53
 * @desc 添加当前类的描述信息
 */
@Service
@Slf4j
@Transactional
public class AccountServiceIml implements AccountService {

    @Autowired
    private AccountDao accountDao;

    @Autowired
    private DuplicationDao duplicationDao;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    @Override
    public void sendMsg(AccountChangeEvent accountChangeEvent) {

        // 设置一个事务日志的唯一id
        String txId = UUID.randomUUID().toString();
        accountChangeEvent.setTxNo(txId);

        // 转换为字符串
        String msgStr = JSON.toJSONString(accountChangeEvent);

        // 创建消息
        Message<String> buildMsg = MessageBuilder.withPayload(msgStr).build();

        // 发送消息（注意这个参数tx_producer_group不要和配置文件中的设置为一样了）
        rocketMQTemplate.sendMessageInTransaction("tx_producer_group","transfer-topic",buildMsg,null);

        // 打印日志
        log.info("发送的消息为，半事务消息{}",msgStr);

    }

    @Override
    public void updateAccountBalance(AccountChangeEvent accountChangeEvent) {

        // 幂等判断，如果已经有转账了，就不要发了
        if(duplicationDao.existsById(accountChangeEvent.getTxNo())) {
            return;
        }

        // 更新账户
        accountDao.updateAccount(accountChangeEvent.getAccountNo(),accountChangeEvent.getAmount());

        // 添加事务，用来记录当前转账已经发出了
        duplicationDao.save(new Duplication(accountChangeEvent.getTxNo(),new Date()));

        /*if(accountChangeEvent.getAmount() == 30){
            throw new RuntimeException("手工制造异常");
        }*/

    }
}
